#!/bin/sh
# translate using t12s (technosaurus) method
# 2011-11-14 L18L
#
# developer: never ever change a message, use a blank ID instead
#            example: if you want to change
#            _M5_:-...failed
#            then use
#            _M_:-...oops this failed
#            that is because original translation is stored nowhere
# note, simple quote (') inside message is not allowed, use (´) instead
# translate to dummy language xxx thus you can test completeness and design
#
#20111115 enabling variables in message, example: '${1}' not found
# not yet tested!!!!!!!!! but anyhow: without variables it is OK
#20111116 bugfix for empty language in 'Select code of language' dialog
version='0.4.1' # bug fix for breaking script in automatic numbering
version='0.4.2' # added check for selected script
version='0.4.3' # bugfix and code clean up
version='0.4.4' # bugfix slash inside message, delimiter for sed is backtick
version='0.4.5' # bugfixes:utf8, enabled using \"
version='0.4.5.1' # bugfix:xxx
                           
RESTART=$0
myfile=$1
OUTPUT_CHARSET=UTF-8 # needed?
T=/usr/share/locales # TEXTDOMAINDIR
title="t12s -v $version "

[ "`whoami`" != "root" ] && exec sudo -A ${0} ${@} # write to TEXTDOMAINDIR

delim='`' # delimiter for sed, no backtick in messages !

# make sure UTF-8 is enabled
if [ "${LANG#*.}" = "$LANG" ]; then 
 yad --text=" <big>Enable <span color='red'>UTF-8</span> in the following dialog
 then restart X server and start again please</big>"
 [[ $? -eq 1 || $? -eq 252 ]] && exit 0 
 /usr/sbin/chooselocale
 ln -s "`pwd`/$RESTART" ${HOME}/Startup/t12s
 exit 0
else
 rm ${HOME}/Startup/t12s 2>/dev/null 
fi 

# the following texts will hopefully give you the idea of this script
text0="script is not yet 
 internationalized by method t12s, sorry."
text1=" Select a script which uses t12s method for internationalisation.
 Translatable text strings are marked by <span color='red'>_M_</span> in such scripts.
 (Developers: klick ´Developer´ button for info how to  Internationalize shell scripts using this method)"
text2=" Select code of language
 which you want to translate to.
 
 Choose from <span color='darkgreen'>existing</span> translations 
 or
 enter <span color='red'>new</span> language code
  Inofficial languages (example: slv for Slavio) possible.
  Regional variants (dialect) appreciated!
  examples: pt_BR or en_AUS
"
text3=" Select <span color='red'>one message</span> which you want to translate.
 The original English message will be shown
 after klicking <span color='darkgreen'>OK</span> button.
 
 Or <span color='red'>Undo</span> translation of last message!"

available_lang_list=/dev/shm/available_languages # temporary list
my_LANG=${LANG%_*} # wild guess: user wants to translate to his language


# select shell script which has this method of i18n
[ -z $myfile ] && while [ 1=1 ]; do # main window ===========================
                  ### some docu added here !
 # select shell script myfile which has this method of i18n
 myfile=$(yad --title="$title Select 1 Script" --text="$text1" \
              --width="500" --height="400" \
              --file-selection --filename=/usr/sbin/ \
              --button="Developer:4" \
              --button="Translator:3" \
              --button="gtk-about:2" \
              --button="gtk-quit:1" \
              --button="gtk-ok:0" \
              )
 choice=$?
 case $choice in
     0) this_LANG=${this_LANG%|*} # cut -d '|' -f 1 `
        [ "`grep _M_ $myfile`" ] && [ -x "$myfile" ] && break # this_LANG preselected for translation
        text=" $myfile $text0"
        [ ! -x "$myfile" ] && text="Sorry, $myfile is not executable"  
        read LINE < $myfile ; [ ${LINE:0:3} != "#!/" ] && text="Sorry, $myfile is no script"  
        yad --text="$text" ; [[ $? -eq 1 || $? -eq 252 ]] && exit 0
        ;;
 1|252) exit 0 ;;
     2) yad --width="450" --title="About t12s : translate 1 script to several languages" \
            --text="  GUI for fast and easy l10n (localization) of shell scripts
            
       There is just a language file containing translations
       from original messages created from source at run time.
            
            core algorithm by Technosaurus
            <small>http://bashismal.blogspot.com/2011/10/
            localizing-shell-scripts-without.html</small>
            
       written by L18L 2011, licence is GPL v3" \
            --button="gtk-ok"
        ;;
     3) yad --title="t12s: some Notes for Translators" \
            --text="
     
   You can translate to <span color='darkgreen'>any</span> language
   without needing their locale (though it might be better).
     
   Your will find your translation of <span color='darkred'>script</span> in this file:
    ${T}/&lt;your language code&gt;/<span color='darkgreen'>script</span>

 Just <b>select a script that is internationalized using this method</b>.
     "      --button="gtk-ok"
        ;;
     4) yad --title="t12s: some Notes for Developpers" \
            --text="  Some simple rules for i18n (internationalization) of shell script:

###################### copy this block into any other script that... ##########
app=\`basename \$0\`
T=/usr/share/locales # TEXTDOMAINDIR
# a one-liner to find existing translation file LOCALES allowing 'dialects'
[ ! -f \${T}/\${LANG%.*}/\${app} ] &amp;&amp; LOCALES=\${T}/\${LANG%_*}/\${app} || LOCALES=\${T}/\${LANG%.*}/\${app}
[ -f \$LOCALES ] &amp;&amp; . \$LOCALES # (re)load translation file (when using variables)
###################### ... uses this _ M _ method of internationalization #####

      
      - mark messages by _M_, no { } for variables, example
        change:
        echo \"Hello \${myOS} world\"
        to:
        [ -f \$LOCALES ] &amp;&amp; . \$LOCALES
        echo \"<span color='darkgreen'>\${_M_:-</span>Hello \$myOS world<span color='darkgreen'>}</span>\"

      - using square or round brackets [ ( then
        alway 1 space after and 1 space before: ) ]
      
      - use \" only if really needed. Try instead ' or ´ (single quote or apostrophe) 

      - 1 message per code line only  
      
  You can start preparing just some messages and after having chosen the script in the main window
  if you are asked for the language to translate to you can type in Language code <b>xxx</b>.
  Then your internationalized script will run in a dummy language, that is just your original messages
  embedded in +++ (Other languages tend to be larger than English messages)
  This way you can check completeness of i18n and possible (hopefully not) break of your screen design." \
         --button="gtk-ok"
        ;;               
 esac
done # /main window ==========================================================

app="`basename $myfile`"
echo app=$app
if [ "`grep -E '^[^#].*_M_:-' $myfile`" ]; then # id numbering of messages
 # find last highest number i to skip
 echo find last highest number i to skip

 sed -e "s${delim}.*{_M_${delim}${delim};s${delim}:-}.*${delim}${delim}" $myfile | grep -E '^[0-9]' | sort -unr > /dev/shm/t12s_i

 read LINE < /dev/shm/t12s_i # head -n 1
 i=${LINE%%:*}                # cut -d ':' -f 1
 [ $i ] || i=0 # found last highest number i to skip
 echo i=$i is highest existing number
 #sort uniq just the (new added) message text
 grep -E '^[^#].*_M_:' $myfile | cut -d "{" -f 2- | rev | cut -d "}" -f 2- | rev \
  | sed -r "s${delim}_M_:-${delim}${delim}g" | sort -u > /dev/shm/t12s_${app}_u
  #echo "last one dummy" >> /dev/shm/t12s_${app}_u # without this last one is missing
 echo "
  new unique numbered messages will be line numbers in /dev/shm/t12s_${app}_u added to $i
  press ENTER to continue
  automatic addition of identifiers to _M_ in
    $myfile
  a backup of $myfile
  will be made as
    ${myfile}_bak." 
 #read x
 cp ${myfile} ${myfile}_bak

 # put id numbers into myfile
 while read LINE ; do # just 1 second, sed ///g needed for multiple use, example: please wait...
  i=$(($i + 1))
  [[ $LINE =~ "[" ]] && LINE=`echo $LINE | sed -e 's/\[/\\\[/g;s/\]/\\\]/g'` # escape square [brackets]
  [[ $LINE =~ "(" ]] && LINE=`echo $LINE | sed -e 's/\(/\\\[/g;s/\)/\\\)/g'` # escape square [brackets]
  [[ $LINE =~ "<" ]] && LINE=`echo $LINE | sed -e 's/</\</g;s/>/\>/g'` # escape <brackets>
  [[ $LINE =~ "\'" ]] && LINE=`echo $LINE | sed -e "s/\'/\\\'/g;"` # escape single quote
  [[ $LINE =~ '\"' ]] && LINE=`echo $LINE | sed -e 's/\"/\\\"/g;'` # escape double quote

  # not working for \"
  sed -e "s${delim}_M_:-${LINE}${delim}_M_${i}:-${LINE}${delim}g" ${myfile} > ${myfile}_$i
  # need to test file sizes, success if different
  if [[ `ls -l ${myfile}_$i | cut -d ' ' -f 5` -gt `ls -l ${myfile} | cut -d ' ' -f 5` ]]; then
   mv ${myfile}_$i ${myfile}
  else #always if \" was used
   chmod +x ${myfile}
   yad --text="Sorry, could not write number $i for 
   $LINE 
You have to add unique number $i manually to _M_ in 
 $myfile
now then press OK button to restart t12s" --button="gtk-ok:0"
   sync; $RESTART $myfile && exit 1
  fi 
 done < /dev/shm/t12s_${app}_u
 chmod +x ${myfile}
 sync
 
fi # /id numbering of messages

# start with user's language, English have to type in 
[ "${LANG%_*}" != "en" ] || this_LANG=${LANG%_*}
# endless loop for translating myfile to several languages ##############
while [ 1=1 ]; do

 # existing_translations for app in TEXTDOMAINDIR, one of them could be new
 cd ${T}
 existing_translations="`ls */${app} 2>/dev/null | tr -s ' ' | cut -d '/' -f 1 `"
 echo -n > $available_lang_list
 for x in $existing_translations; do echo $x >> $available_lang_list; done
 cd - 1>/dev/null
 sync # ? needed

 # choose language $this_LANG
 this_LANG=''
 while [ "`echo $this_LANG | sed -r 's/[a-z]{2,3}(_[A-Z]{2,3}){0,1}/OK/'`" != "OK" ]; do #20111116
  this_LANG=$(yad --title="$title translate $app" --text="$text2" \
                  --width="80" --height="240" \
                  --form \
                  --item-separator="\n" \
                  --field="Language code:CBE" "`echo ${my_LANG} ; cat $available_lang_list`" \
                  --item-separator="\n" \
                  --button="gtk-quit:1" \
                  --button="gtk-ok:0" \
             ) 
  choice=$?
  case $choice in
       0) this_LANG=${this_LANG%|*};; # cut -d '|' -f 1 `
   1|252) exit 0 ;;
  esac
 done
 echo $this_LANG
 [ ! -d "${T}/${this_LANG}" ] && mkdir ${T}/${this_LANG}

 # extract English messages from script: create temporary English language file
  grep _M_ $myfile | cut -d "{" -f 2- | rev | cut -d "}" -f 2- | rev \
     | sed -r "s${delim}:-${delim}=\"${delim}g;s${delim}\$${delim}\"${delim}g" | sort -u > /dev/shm/t12s_${app}_en

 # dialect starts with copy of base language, ex: fr_CA copied from fr
 if [ ${#this_LANG} -gt 4 -a ! -f ${T}/${this_LANG}/${app} ]; then
    cp ${T}/${this_LANG%_*}/${app} ${T}/${this_LANG} 
    [ $! ] || existing_translations="$existing_translations ${this_LANG}"
 fi   

 # merge existing translation
 if [[ `grep -E "^${this_LANG}$" $available_lang_list` ]]; then # merge
  mv ${T}/${this_LANG}/${app} ${T}/${this_LANG}/${app}_tmp
  while read LINE; do #comment for no more existing ones, but once only
   [ "`grep -E ${LINE%=*} /dev/shm/t12s_${app}_en`" ] && comment="" || comment="#"
   [[ "${LINE:0:1}" = "#" ]] && comment=""
   echo ${comment}${LINE} >> ${T}/${this_LANG}/${app}
  done < ${T}/${this_LANG}/${app}_tmp
  rm ${T}/${this_LANG}/${app}_tmp
  while read LINE; do #append new ones
   [ "`grep -E ${LINE%=*} ${T}/${this_LANG}/${app}`" ] \
   || echo $LINE >> ${T}/${this_LANG}/${app}
  done < /dev/shm/t12s_${app}_en
 else
  if [ "$this_LANG" = "xxx" ]; then # dummy language
   # emulating translation (messages just embedded in +++)
   sed -e "s${delim}=\"${delim}=\"+++${delim}g;s${delim}\"${delim}+++\"${delim}g" /dev/shm/t12s_${app}_en > ${T}/xxx/${app}
   LANG=xxx 
   exec $myfile &
   break

  elif [ 1 = 2 ] ; then #automated translation available...
  
  FROM=/C/
 [ ! -d /usr/share/locales/C/ ] && mkdir /usr/share/locales/C/
 for x in $myfile ; do 
  TEMPLATE=/usr/share/locales/C/${app}.txt
  while read -d$ A || [ "$A" ]; do
     case "$A" in
        *{_M_*)B=_M${A##*_M};B=${B%%\}*};echo ${B//:-/=};;
     esac
  done < $x >${TEMPLATE}
  mv ${TEMPLATE} ${TEMPLATE}m; sort -u ${TEMPLATE}m>${TEMPLATE}; rm ${TEMPLATE}m
  for x in $this_LANG ; do
   TO=/${x//-/_}/
   [ ! -d ${TEMPLATE%%/C/*}/${x//-/_} ] && mkdir ${TEMPLATE%%/C/*}/${x//-/_}
   curl -A firefox \
    -F "file=@$TEMPLATE;type=text/plain" \
    -F "sl=en" \
    -F "tl=$x" \
    http://translate.googleusercontent.com/translate_f | \
    while read A || [ "$A" ]; do
      case $A in
         "<meta"*)A="";;
         *"<pre>"*)A=${A##*"<pre>"};;
         *"</pre>"*)A=${A%%"</pre>"*};;
      esac
      [ "$A" ] && echo ${A// = /=\"}\"
    done > ${TEMPLATE//$FROM/$TO}
    mv ${T}/${x}/${app}.txt  ${T}/${x}/${app}
    #
    #curl: (6) Couldn't resolve host 'translate.googleusercontent.com' : empty file
    #
    # file is not utf-8 but iso-8859
    #
   done
   rm $TEMPLATE
  done  #automated translation available...
   
  else # copy English to this_LANG 
   cp /dev/shm/t12s_${app}_en ${T}/${this_LANG}/${app}
  fi 
 fi
 
 # loop translate 1 item -------------------------------------------------------
 # while [ 2=2 ]; do
 [ "$this_LANG" = "xxx" ] && $myfile || while [ 2=2 ]; do
  sed -r "s${delim}=\"${delim}\n${delim}g;s${delim}\"\$${delim}${delim}g" ${T}/${this_LANG}/${app} > /dev/shm/t # just for inspection
  message=$(cat /dev/shm/t \
           | yad --title="$title translate $app to $this_LANG" \
                 --height="400" --text="$text3" \
                 --list \
                 --column="ID" \
                 --column="Actual Message Translated To ${this_LANG//_/_ }:TEXT" \
                 --button="Change Language:3" \
                 --button="gtk-execute:2" \
                 --button="gtk-quit:1" \
                 --button="gtk-undo:9" \
                 --button="gtk-ok:0" \
           )    
  choice=$?
  case $choice in
   1|252) exit 0 ;;
       3) break ;;
       2) 
          LANG="${this_LANG}" # Gtk-WARNING **: Locale not supported by C library.
                              # but sufficient for just language   
          [ -x $myfile ] || yad --text="sorry, chosen $myfile is not executable" \
                         && exec $myfile & ;;
       0) if [ "$message" ]; then
           msgID="`echo $message | cut -d '|' -f 1`" # ${message%|*} no go
           msgtr="`echo $message | cut -d '|' -f 2`"
           msgEN="`grep -F ${msgID}= /dev/shm/t12s_${app}_en | cut -d '\"' -f 2`"
           if [ -z "$msgEN" ];then
            yad --text="not in use any more"
           else 
            msgEN="$msgEN"
            new_msgtr=$(yad --title="translate" --width="600" --text="$msgEN" \
                   --entry --entry-text="$msgtr" \
                   --button="gtk-ok:0" )
            [ "$new_msgtr" = "$msgtr" ] && continue
            # update translation file
            mv ${T}/${this_LANG}/${app} ${T}/${this_LANG}/${app}_old
            while read LINE; do
             [ "${LINE%=*}" != "$msgID" ] && out="$LINE" || out="${msgID}=\"${new_msgtr}\""
             echo $out >> ${T}/${this_LANG}/${app} 
            done < ${T}/${this_LANG}/${app}_old
           fi 
          else
           yad --title="translate" \
               --text="Select a line before OK button please" \
               --button="gtk-ok:0"
          fi ;;
       9) cp ${T}/${this_LANG}/${app}_old ${T}/${this_LANG}/${app} ;;
  esac

 done # /loop translate item --------------------------------------------------

done # /endless loop for translating myfile to several languages ##############

#end of script